package com.jinzhi.jzweb.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.jinzhi.common.service.DictService;
import com.jinzhi.common.utils.Result;
import com.jinzhi.jzapi.examination.pojo.ExaminationsVo;
import com.jinzhi.jzweb.domain.*;
import com.jinzhi.jzweb.pojo.ExaminationAnswerSheetComVO;
import com.jinzhi.jzweb.pojo.ExaminationAnswerSheetComVOS;
import com.jinzhi.jzweb.pojo.ModuleConfig.SignGradeDTO;
import com.jinzhi.jzweb.pojo.MrkRefereeVO;
import com.jinzhi.jzweb.pojo.StuSignUpTeamVo;
import com.jinzhi.jzweb.service.*;
import com.jinzhi.jzweb.utils.ZipFileUtils;
import com.jinzhi.oss.controller.FileController;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.record.chart.LinkedDataRecord;
import org.springframework.beans.BeanUtils;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;

import com.jinzhi.jzweb.dao.MarkDao;
import com.jinzhi.common.base.CoreServiceImpl;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 
 * <pre>
 * 打分表
 * </pre>
 * <small> 2023-06-19 08:45:15 | lance</small>
 */
@Service
public class MarkServiceImpl extends CoreServiceImpl<MarkDao, MarkDO> implements MarkService {


    private final MarkDao markDao;


    private final ExaminationAnswerSheetComService examinationAnswerSheetComService;

    private final StuSignUpComService stuSignUpService;

    private final ExaminationBatchService examinationBatchService;

    private final DictService dictService;

    private final FileController fileController;

    private final ExaminationBatchComService examinationBatchComService;

    public MarkServiceImpl(MarkDao markDao, ExaminationAnswerSheetComService examinationAnswerSheetComService, StuSignUpComService stuSignUpService, ExaminationBatchService examinationBatchService, DictService dictService, FileController fileController, ExaminationBatchComService examinationBatchComService) {
        this.markDao = markDao;
        this.examinationAnswerSheetComService = examinationAnswerSheetComService;
        this.stuSignUpService = stuSignUpService;
        this.examinationBatchService = examinationBatchService;
        this.dictService = dictService;
        this.fileController = fileController;
        this.examinationBatchComService = examinationBatchComService;
    }




    @Override
    public Page<MarkDO> selectListPageMarkDO(int current, int number, Map map) {
        // 新建分页
        Page<MarkDO> page = new Page<MarkDO>(current, number);
        List<MarkDO> markDOS = this.baseMapper.selectListMarkDO(page,map);
        return page.setRecords(markDOS);
    }

    @Override
    public Page<MarkDO> selectListPageMarkDOSecure(ExaminationsVo examinationsVo) {
        // 新建分页
        Page<MarkDO> page = new Page<MarkDO>(examinationsVo.getCurrent(),examinationsVo.getNumber());
        List<MarkDO> markDOS = baseMapper.selectListPageMarkDOSecure(page, examinationsVo);
        return page.setRecords(markDOS);
    }

    @Override
    public Page<MarkStatisticsVO> selectListPageMarkStatisticsVO(int current, int number, Map map) {
        // 新建分页
        Page<MarkStatisticsVO> page = new Page<MarkStatisticsVO>(current, number);
        List<MarkStatisticsVO> markStatisticsVOS = this.baseMapper.selectListPageMarkStatisticsVO(page,map);
        return page.setRecords(markStatisticsVOS);
    }

    @Override
    public List<MarkStatisticsVO> selectListMarkStatisticsVO(Map map) {
        return this.baseMapper.selectListPageMarkStatisticsVO(map);
    }

    @Override
    public List<MarkDO> selectListMarkDO(Map map) {
        List<MarkDO> markDOS = this.baseMapper.selectListMarkDO(map);
        return markDOS;
    }

    @Override
    public List<MarkVO> selectListMarkVO(Map map) {
        return baseMapper.selectListMarkVO(map);
    }

    @Override
    public List<MrkRefereeVO> selectRefereeId(Map map) {
        return baseMapper.selectRefereeId(map);
    }

    @Override
    public String selTotalScore(Map map) {
        String competition = (String) map.get("competition");
        //如果为A赛场
        if (competition.equals("A")){
            return baseMapper.selTotalScore(map);
        }
        return baseMapper.selTotalScoreBC(map);
    }

    @Override
    public List<Double> selMaxMinScore(Map map) {
        return baseMapper.selMaxMinScore(map);
    }

    @Override
    public List<Double> selMaxMinScoreA(Map map) {
        return baseMapper.selMaxMinScoreA(map);
    }

    public List<Double> selMaxMinScoreStudent(Map map) {
        return baseMapper.selMaxMinScoreStudent(map);
    }


    @Override
    public List<MarkVO> selEditData(Map map) {
        return baseMapper.selEditData(map);
    }

    @Override
    public List<MarkVO> sleMarkByebatchIdAndSignId(Map map) {
        return this.baseMapper.sleMarkByebatchIdAndSignId(map);
    }

    @Override
    public  List<String> selScoreABC(Map map) {
        return baseMapper.selScoreABC(map);
    }

    @Override
    public List<MarkVO> seleScoreTopicContent(Map map) {
        return baseMapper.seleScoreTopicContent(map);
    }

    @Override
    public List<MarkVO> selectAListScore(Map map) {
        return markDao.selectAListScore(map);
    }

    @Override
    public List<MarkVO> selectAListStatusScore(Map map) {
        return markDao.selectAListStatusScore(map);
    }

    @Override
    public List<MarkVO> seleScoreTopicContentStandby(Map map) {
        return baseMapper.seleScoreTopicContentStandby(map);
    }

    @Override
    public List<MarkVO> selectAScore(Map map) {
        return baseMapper.selectAScore(map);
    }

    @Override
    public List<MrkRefereeVO> selectReferee(Map map) {
        return markDao.selectReferee(map);
    }

    @Override
    public List<MarkVO> selectMark(Map map) {
        return markDao.selectMark(map);
    }

    @Override
    public List<MrkRefereeVO> selectRefereeSize(Map map) {
        return baseMapper.selectRefereeSize(map);
    }

    @Override
    public List<MarkVO> selectRefereeBCSize(Map map) {
        return baseMapper.selectRefereeBCSize(map);
    }

    @Override
    public Result stuFileDownload(Long cbatchId, HttpServletResponse response){
        //获取批次名称
        String baName =  examinationBatchService.selectById(cbatchId).getName();
        //根据赛场id获取考生信息
        List<StuSignUpComDO> signs = stuSignUpService.selectList(new EntityWrapper<StuSignUpComDO>().eq("cbatch_id",cbatchId));
        if(signs.isEmpty()){
            return Result.fail("考生信息为空");
        }
        List<Long> stuIds = signs.stream().map(StuSignUpComDO::getId).collect(Collectors.toList());
        //根据考生id集合获取考生文件链接
        List<ExaminationAnswerSheetComDO> exs = examinationAnswerSheetComService.selectList(new
                EntityWrapper<ExaminationAnswerSheetComDO>().in("stu_sign_id",stuIds));
        //筛选出有附件的考生答卷
        List<ExaminationAnswerSheetComDO> files = exs.stream().filter(a -> !StringUtils.isBlank(a.getFile())).distinct().collect(Collectors.toList());
        if(files.isEmpty()){
            return Result.fail("没有可下载的附件");
        }
        //添加二次加密号
        files.forEach(a -> signs.forEach(b ->{
            if(Objects.equals(a.getStuSignId(),b.getId())){
                a.setNum2(b.getNum2());
            }
        }));
        Map<String, String> map =new HashMap<>();
        map.put("type","foundZip");
        map.put("name","foundZip");
        String foundZip = dictService.selDicBy(map);
        //调用文件接口

        return Result.ok(foundZip(files,baName,response,foundZip));
    }

    /**
     * 考生成绩统计
     * @param markDO
     * @return
     */
    @Override
    public MarkVO queryScoreStatistics(MarkDO markDO) {
        MarkVO resultVO = new MarkVO();
        //查询每个区间成绩的数量
        List<MarkVO> markVOS = markDao.selectScoreStatistics(markDO);
        Integer groupNum = 0;//汇总区间的成绩数量
        if(markVOS!=null){
            // 统计区间成绩的总数量
            for (MarkVO markVO : markVOS) {
                groupNum += markVO.getGroupNum();
            }
            //计算每个区间的数量占比
            DecimalFormat df = new DecimalFormat("#.00");
            for (MarkVO markVO : markVOS) {
                double proportion = (double) markVO.getGroupNum() / groupNum * 100;
                double formattedProportion = Double.parseDouble(df.format(proportion));
                markVO.setProportion(formattedProportion);
            }
        }
        resultVO.setMarkVOList(markVOS);

        //查询 A-职业素养、A-案例分析、B-器官异物处理、B-体温测量、C-生活照料、C-早期发展指导 的分数差值（满分、最高分、最低分、平均分、分差值）
        List<MarkVO> markDifference = markDao.selectScoreDifference(markDO);
        if (null != markDifference) {
            // 使用流操作进行分组和统计
            List<MarkVO> markVOList = calculateScore(markDifference);
            resultVO.setMarkDifferenceList(markVOList);
        }


        return resultVO;
    }


    /**
     * 计算分数差值（满分、最高分、最低分、平均分、分差值）
     * @param markDifference
     * @return
     */
    public static List<MarkVO> calculateScore(List<MarkVO> markDifference){

        List<MarkVO> resultList = new ArrayList<>();
        // 使用流操作进行分组
        Map<String, List<MarkVO>> groupedData = markDifference.stream()
                .collect(Collectors.groupingBy(MarkVO::getTopicName));

        // 遍历每个分组并输出统计结果
        groupedData.forEach((topicName, markVOList) -> {
            //求最大值
            double maxScore = markVOList.stream()
                    .mapToDouble(MarkVO::getUpdateScore)
                    .max()
                    .orElse(0.0);
            //求最小值
            double minScore = markVOList.stream()
                    .mapToDouble(MarkVO::getUpdateScore)
                    .min()
                    .orElse(0.0);
            //求平均值
            double averageScore = markVOList.stream()
                    .mapToDouble(MarkVO::getUpdateScore)
                    .average()
                    .orElse(0.0);
            //每组数据量
            long count = markVOList.size();

            // 获取每组中的一个score值(满分)
            double score = Double.parseDouble(markVOList.get(0).getScore());
            //分差
            double poor = maxScore - minScore;

            MarkVO markVO = new MarkVO();
            markVO.setMaxScore(maxScore);
            markVO.setMinScore(minScore);
            markVO.setAverageScore(averageScore);
            markVO.setCount(count);
            markVO.setPoor(poor);
            markVO.setScore(String.valueOf(score));
            markVO.setTopicName(topicName);
            resultList.add(markVO);
        });

        return resultList;

    }


    /**
     * 录分保存
     * @param examinationsVo
     * @return
     */
    @Override
    public Result recordASave(List<MarkDO> markDOS) {
        if(!markDOS.isEmpty()){
            for (MarkDO markDO : markDOS) {
                if(markDO.getId()!=null){
                    this.updateById(markDO);
                } else{
                    markDO.setStatus(0);
                    this.insert(markDO);
                }
            }
        }

        return Result.ok();
    }




    /**
     * 封装文件接口
     */
    private String foundZip(List<ExaminationAnswerSheetComDO> files,String baName,HttpServletResponse response,String foundZip){
        try {
            List<File> file = new ArrayList<>();
            for (int j = 0; j < files.size(); j++) {
                URL url = new URL(files.get(j).getFile());
                String fileName = url.getFile();
                // 打开到该URL的连接
                URLConnection conn = url.openConnection();
                // 从连接中获取输入流
                InputStream in = conn.getInputStream();
                // 创建一个临时文件来存储下载的映像
                Date date = new Date();
                String dateStr = new SimpleDateFormat("yyyy-MM-dd").format(date);
                File tempFile = File.createTempFile("A"+files.get(j).getNum2().toString()+"-" + dateStr +"-",  fileName.substring(fileName.lastIndexOf(".")));
                // 创建一个输出流，将映像写入临时文件
                FileOutputStream out = new FileOutputStream(tempFile);
                // 从输入流中读取文件并将其写入输出流
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesRead);
                }
                // 关闭输入和输出流
                in.close();
                out.close();
                // 打印临时文件的路径
                System.out.println("Downloaded file saved as "+tempFile.getAbsolutePath());
                File file1  = new File(tempFile.getAbsolutePath());
                file.add(file1);

            }
            String fileName = foundZip + baName + ".zip";
            System.out.println("Downloaded Zip saved as"+fileName);
            //压缩文件
            ZipFileUtils.generateZip(new File(fileName), file, false);
            //下载文件
            //ZipFileUtils.download(new File(fileName),response);
            //ZipFileUtils.downloadZip(new File(fileName),response);
            //把临时文件上传至服务器
            File filess = new File(fileName);
            MultipartFile cMultiFile = new MockMultipartFile("file", filess.getName(), null, new FileInputStream(filess));
            //上传成功后删除临时文件
            filess.delete();
            return fileController.upload(cMultiFile).getData();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {

        }
    }
}
